package com.ctshk.rpc.localfun.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.req.MainData;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.common.utils.process.ProcessorUtil;
import com.ctshk.rpc.localfun.dto.*;
import com.ctshk.rpc.localfun.entity.*;
import com.ctshk.rpc.localfun.enums.ProductCenterEnum;
import com.ctshk.rpc.localfun.mapper.*;
import com.ctshk.rpc.localfun.req.*;
import com.ctshk.rpc.localfun.req.cache.LocalFunProductCacheOpsReq;
import com.ctshk.rpc.localfun.service.ILocalFunAppProductService;
import com.ctshk.rpc.localfun.service.ILocalFunCostPriceService;
import com.ctshk.rpc.localfun.service.ILocalFunResourceService;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
//import io.seata.spring.annotation.GlobalTransactional;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description 当地游玩-资源中心-业务逻辑实现
 * @Author wansi <gaylen15527491065@yeah.net>
 * @Date 2021/3/23
 */
@Slf4j
@Service
@DubboService
public class LocalFunResourceServiceImpl extends ServiceImpl<LocalFunProductMapper, LocalFunProduct>  implements ILocalFunResourceService {

    @Autowired
    private LocalFunProductMapper localFunProductMapper;
    @Autowired
    private LocalFunProductCostStrategySpecAttrMapper strategySpecAttrMapper;
    @Autowired
    private LocalFunProductCostStrategySpecStockMapper localFunProductCostStrategySpecStockMapper;
    @Autowired
    private LocalFunProductCostStrategyMapper localFunProductCostStrategyMapper;
    @Autowired
    private LocalFunProductCostStrategyVaildDateMapper localFunProductCostStrategyVaildDateMapper;
    @Autowired
    private ILocalFunCostPriceService iLocalFunCostPriceService;
    //汇率服务
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;

    @DubboReference
    private ISysUserService iSysUserService;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private ISysApprovalService iSysApprovalService;
    @DubboReference
    private ISysPermissionService sysPermissionService;
    @DubboReference
    private ILocalFunAppProductService iLocalFunAppProductService;

    @Override
    public PageResponse<LocalFunResourceDTO> queryList(LocalFunResourceReq req, TokenUser currentUser) {

        IPage<LocalFunProduct> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        //不是管理员
        List<Long> data = Lists.newArrayListWithCapacity(5);
        if (!GlobalConstants.Role.isAdmin(currentUser.getUsername())) {
            if (req.getMenuId() == null) {
                throw new BusinessException(SystemError.SYSTEM_2106);
            }
            Result<List<Long>> permissionResult = sysPermissionService.queryPermission(req.getMenuId(), currentUser.getId());
            if (!permissionResult.isSuccess()) {
                SystemError result = SystemError.getDefined(permissionResult.getCode());
                throw new BusinessException(result);
            }
            data.addAll(permissionResult.getData()) ;
        }

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //分页查询结果集
        Page<LocalFunProduct> insuranceIPage = baseMapper.querySourceProductList(req,data,iPage);
        stopWatch.stop();
        log.info("query SQL cost time："+ stopWatch.prettyPrint() +"ms");

        if (CollectionUtils.isNotEmpty(insuranceIPage.getRecords())) {

            stopWatch.start();
            List<LocalFunResourceDTO> localFunResourceDTOList = EntityUtil.copyList(insuranceIPage.getRecords(), LocalFunResourceDTO.class);
            try {
                localFunResourceDTOList.forEach(entity->{
                    if (entity.getChargeUserId() != null) {
                        UserDTO userDTO = null;
                        try {
                            userDTO = iSysUserService.loadUserByParam(entity.getChargeUserId(), 1);
                            entity.setChargeUser(userDTO.getCreateDept());
                        } catch (Exception e) {
                            Result.failed(SystemError.SYS_500);
                        }
                    }
                });
            } catch (Exception e) {
                log.error("设置负责人名称/部门失败：{}",e.getMessage());
            }
            ProcessorUtil.processMore(localFunResourceDTOList,LocalFunResourceDTO.class);
            stopWatch.stop();
            log.info("cost time："+ stopWatch.prettyPrint() +"ms");

            return new PageResponse<>(localFunResourceDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public List<LocalFunResourceDTO> queryListByProductIds2(LocalFunResourceReq localFunResourceReq) {
        //查询条件
        QueryWrapper<LocalFunProduct> queryWrapper = queryParamCondition(localFunResourceReq, null);
        List<LocalFunProduct> localFunProducts = baseMapper.selectList(queryWrapper);
        return EntityUtil.copyList(localFunProducts, LocalFunResourceDTO.class);
    }

    @Override
    public Result<Long> updateSaleStatus(LocalFunResourceSaleReq localFunResourceSaleReq, TokenUser tokenUser) {
        baseMapper.selectBatchIds(localFunResourceSaleReq.getIds())
                .forEach(LocalFun -> {
                    LocalFun.setSaleStatus(localFunResourceSaleReq.getSaleStatus());
                    LocalFun.setGmtModified(LocalDateTime.now());
                    LocalFun.setModifiedId(tokenUser.getId());
                    baseMapper.updateById(LocalFun);
                });

        //恢复有效产品
        if(localFunResourceSaleReq.getSaleStatus() == 1){
            try {
                CompletableFuture.runAsync(() -> {
                    LocalFunProductCacheOpsReq req = new LocalFunProductCacheOpsReq();
                    req.setIds(localFunResourceSaleReq.getIds());
                    iLocalFunAppProductService.cacheUpdate(req);
                });
                log.info("[当地玩乐-产品设置] 同步缓存成功");
            } catch (Exception e) {
                log.info("[当地玩乐-产品设置] 同步缓存失败：{}",e.getMessage());
            }
        }else {
            try {
                CompletableFuture.runAsync(() -> {
                    LocalFunProductCacheOpsReq req = new LocalFunProductCacheOpsReq();
                    req.setIds(localFunResourceSaleReq.getIds());
                    iLocalFunAppProductService.deleteCache(req);
                });
                log.info("[当地玩乐-产品设置] 清除无效产品缓存成功");
            } catch (Exception e) {
                log.info("[当地玩乐-产品设置] 清除无效产品缓存失败：{}",e.getMessage());
            }
        }
        return Result.success(localFunResourceSaleReq.getIds().get(0));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Long> save(LocalFunResourceProductReq resourceProductReq, TokenUser tokenUser) {

        //校验当地玩乐成本有效期是否重复
        if(duplicateDateForUseDate(resourceProductReq)){
            return Result.failed(SystemError.LOCAL_FUN_18003);
        }
        //校验成本编码
        List<LocalFunResourceStrategyReq> LocalFunResourceStrategyReqs = resourceProductReq.getLocalFunResourceStrategy();

        if(resourceProductReq.getId() == null && existedStockNumberError(LocalFunResourceStrategyReqs)){
            return Result.failed(SystemError.LOCAL_FUN_18000);
        }
        //保存产品基本信息
        LocalFunProduct LocalFunProduct = saveProductBaseInfo(resourceProductReq, tokenUser);

        //保存规格成本信息
        saveCostStrategyInfo(LocalFunResourceStrategyReqs, LocalFunProduct);

        return Result.success(LocalFunProduct.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Long> modify(LocalFunResourceProductReq resourceProductReq, TokenUser tokenUser) {
        //清空产品规格陈本信息
        QueryWrapper<LocalFunProductCostStrategyVaildDate> dateQueryWrapper = new QueryWrapper<>();
        dateQueryWrapper.lambda().eq(LocalFunProductCostStrategyVaildDate::getProductId, resourceProductReq.getId());
        localFunProductCostStrategyVaildDateMapper.delete(dateQueryWrapper);

        QueryWrapper<LocalFunProductCostStrategySpecAttr> attrQueryWrapper = new QueryWrapper<>();
        attrQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecAttr::getProductId, resourceProductReq.getId());
        strategySpecAttrMapper.delete(attrQueryWrapper);

        QueryWrapper<LocalFunProductCostStrategySpecStock> specStockQueryWrapper = new QueryWrapper<>();
        specStockQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getProductId, resourceProductReq.getId());
        localFunProductCostStrategySpecStockMapper.delete(specStockQueryWrapper);

        QueryWrapper<LocalFunProductCostStrategy> localFunCostStrategyMapper = new QueryWrapper<>();
        localFunCostStrategyMapper.lambda().eq(LocalFunProductCostStrategy::getProductId, resourceProductReq.getId());
        localFunProductCostStrategyMapper.delete(localFunCostStrategyMapper);

        LocalFunProduct localFunProduct = localFunProductMapper.selectById(resourceProductReq.getId());

        Result<Long> save = save(resourceProductReq, tokenUser);

        //已上架的产品才做缓存更新
        if(localFunProduct.getStatus() == 1 && localFunProduct.getSaleStatus() == 1){
            //刷新缓存
            try {
                CompletableFuture.runAsync(() -> {
                    LocalFunProductCacheOpsReq req = new LocalFunProductCacheOpsReq();
                    req.setIds(Lists.newArrayList(resourceProductReq.getId()));
                    iLocalFunAppProductService.cacheUpdate(req);
                });
                log.info("[当地玩乐-产品设置] 同步缓存成功");
            } catch (Exception e) {
                log.info("[当地玩乐-产品设置] 同步缓存失败：{}",e.getMessage());
            }
        }
        return save;
    }


    /**
     * 保存规格成本信息
     * @param localFunResourceStrategyReqs  成本策略请求参数
     * @param localFunProduct               产品基本信息实体
     */
    private void saveCostStrategyInfo(List<LocalFunResourceStrategyReq> localFunResourceStrategyReqs, LocalFunProduct localFunProduct) {
        localFunResourceStrategyReqs.forEach(LocalFunResourceStrategyReq -> {
            //1.新增产品成本策略基本信息
            LocalFunProductCostStrategy LocalFunProductCostStrategy = insertLocalFunProductCostStrategy(localFunProduct, LocalFunResourceStrategyReq);

            //2.设置产品成本有效期
            addCostStrategyValidDate(localFunProduct, LocalFunResourceStrategyReq, LocalFunProductCostStrategy);

            //3.添加成本规格信息
            addCostStrategySpecAttr(localFunProduct, LocalFunResourceStrategyReq, LocalFunProductCostStrategy);

            //4.设置成本价
            setCostPrice(localFunProduct, LocalFunResourceStrategyReq, LocalFunProductCostStrategy);
        });
    }


    /**
     * 设置成本价
     * @param localFunProduct               产品基本信息
     * @param LocalFunResourceStrategyReq   请求入参
     * @param localFunProductCostStrategy   产品成本基本信息
     */
    private void setCostPrice(LocalFunProduct localFunProduct, LocalFunResourceStrategyReq LocalFunResourceStrategyReq, LocalFunProductCostStrategy localFunProductCostStrategy) {
        List<LocalFunResourceStockReq> LocalFunResourceStock = LocalFunResourceStrategyReq.getLocalFunResourceStock();
        if (CollectionUtils.isNotEmpty(LocalFunResourceStock)) {
            LocalFunResourceStock.stream().map(item -> {
                LocalFunProductCostStrategySpecStock LocalFunProductCostStrategySpecStock = EntityUtil.convertBean(item, LocalFunProductCostStrategySpecStock.class);
                LocalFunProductCostStrategySpecStock.setId(SnowflakeIdWorker.nextId());
                LocalFunProductCostStrategySpecStock.setCostId(localFunProductCostStrategy.getId());
                LocalFunProductCostStrategySpecStock.setProductId(localFunProduct.getId());
                if(StringUtils.isNotEmpty(item.getAttr1Name())){
                    LocalFunProductCostStrategySpecStock.setAttr1Id(speMap.get(item.getAttr1Name()));
                }
                if(StringUtils.isNotEmpty(item.getAttr2Name())){
                    LocalFunProductCostStrategySpecStock.setAttr2Id(speMap.get(item.getAttr2Name()));
                }
                //已售庫存
                LocalFunProductCostStrategySpecStock.setSoldStock(0);
                //可售庫存
                LocalFunProductCostStrategySpecStock.setSurplusStock(LocalFunProductCostStrategySpecStock.getTotalStock());
                return LocalFunProductCostStrategySpecStock;
            }).forEach(localFunProductCostStrategySpecStockMapper::insert);
        }
    }

    private Map<String,Long> speMap = Maps.newConcurrentMap();

    /**
     * 添加成本规格信息
     * @param localFunProduct               产品基本信息
     * @param LocalFunResourceStrategyReq   请求入参
     * @param localFunProductCostStrategy   产品成本基本信息
     */
    private void addCostStrategySpecAttr(LocalFunProduct localFunProduct, LocalFunResourceStrategyReq LocalFunResourceStrategyReq, LocalFunProductCostStrategy localFunProductCostStrategy) {
        List<LocalFunResourceSpecReq> specList = LocalFunResourceStrategyReq.getSpecList();
        if (CollectionUtils.isNotEmpty(specList)) {
            specList.stream().map(item -> {
                LocalFunProductCostStrategySpecAttr LocalFunProductCostStrategySpecAttr = new LocalFunProductCostStrategySpecAttr();
                LocalFunProductCostStrategySpecAttr.setId(SnowflakeIdWorker.nextId());
                LocalFunProductCostStrategySpecAttr.setProductId(localFunProduct.getId());
                LocalFunProductCostStrategySpecAttr.setCostId(localFunProductCostStrategy.getId());
                LocalFunProductCostStrategySpecAttr.setAttributeName(item.getAttributeName());
                LocalFunProductCostStrategySpecAttr.setSpecId(item.getSpecId());
                LocalFunProductCostStrategySpecAttr.setSpecName(item.getSpecName());
                return LocalFunProductCostStrategySpecAttr;
            }).forEach(spc->{
                strategySpecAttrMapper.insert(spc);
                speMap.put(spc.getAttributeName(),spc.getId());
            });
        }
    }


    /**
     * 校验当地玩乐成本有效期是否重复
     * 思路：1.收集开始日期到结束日期的所有结果集合
     * 2.将日期去重和日期集合总数对比，不相等代表存在重复的有效日期
     * @param req
     * @return
     */
    private boolean duplicateDateForUseDate(LocalFunResourceProductReq req) {
        List<LocalFunResourceStrategyReq> strategyList = req.getLocalFunResourceStrategy();
        Set<LocalDate> localDateSet = Sets.newHashSet();
        int localDateSize = 0;
        for (LocalFunResourceStrategyReq airProductCostDataReq : strategyList) {
            List<LocalFunResourceStrategyTimeReq> timeDataList = airProductCostDataReq.getTimeList();
            if(CollectionUtils.isEmpty(timeDataList)){
                return false;
            }
            for (LocalFunResourceStrategyTimeReq airProductCostDateData : timeDataList) {
                LocalDate dateBegin = DateUtil.parse(airProductCostDateData.getTimeBegin()).toLocalDate();
                LocalDate dateEnd = DateUtil.parse(airProductCostDateData.getTimeEnd()).toLocalDate();
                //获取开始日期-结束日期的集合
                List<LocalDate> dates = Stream.iterate(dateBegin, date -> date.plusDays(1))
                        .limit(ChronoUnit.DAYS.between(dateBegin, dateEnd))
                        .collect(Collectors.toList());
                dates.add(dateEnd);
                localDateSet.addAll(dates);
                localDateSize += dates.size();
            }
        }
        return localDateSet.size() != localDateSize;
    }

    private Long getAttrId(LocalFunProduct localFunProduct,Long costId,String attrName){
        QueryWrapper<LocalFunProductCostStrategySpecAttr> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunProductCostStrategySpecAttr::getProductId,localFunProduct.getId());
        queryWrapper.lambda().eq(LocalFunProductCostStrategySpecAttr::getCostId,costId);
        List<LocalFunProductCostStrategySpecAttr> specAttrList = strategySpecAttrMapper.selectList(queryWrapper);

        if(CollectionUtils.isEmpty(specAttrList)){
            return null;
        }

        Map<String, List<LocalFunProductCostStrategySpecAttr>> attrMap = specAttrList.stream().collect(Collectors.groupingBy(LocalFunProductCostStrategySpecAttr::getAttributeName));

        if(StringUtils.isNotEmpty(attrName)){
            List<LocalFunProductCostStrategySpecAttr> costStrategySpecAttrs = attrMap.get(attrName);
            if(CollectionUtils.isNotEmpty(costStrategySpecAttrs)){
                LocalFunProductCostStrategySpecAttr specAttr = costStrategySpecAttrs.stream().findFirst().orElse(null);
                if(specAttr != null){
                    return specAttr.getId();
                }
            }
        }
        return null;
    }

    /**
     * 设置产品成本有效期
     * @param localFunProduct               产品基本信息
     * @param LocalFunResourceStrategyReq   请求入参
     * @param localFunProductCostStrategy   产品成本基本信息
     */
    private void addCostStrategyValidDate(LocalFunProduct localFunProduct, LocalFunResourceStrategyReq LocalFunResourceStrategyReq, LocalFunProductCostStrategy localFunProductCostStrategy) {
        List<LocalFunResourceStrategyTimeReq> timeList = LocalFunResourceStrategyReq.getTimeList();
        if (CollectionUtils.isNotEmpty(timeList)) {
            timeList.forEach(time -> {
                LocalFunProductCostStrategyVaildDate localFunProductCostStrategyVaildDate = EntityUtil.convertBean(time, LocalFunProductCostStrategyVaildDate.class);
                localFunProductCostStrategyVaildDate.setId(SnowflakeIdWorker.nextId());
                localFunProductCostStrategyVaildDate.setCostId(localFunProductCostStrategy.getId());
                localFunProductCostStrategyVaildDate.setProductId(localFunProduct.getId());
                localFunProductCostStrategyVaildDateMapper.insert(localFunProductCostStrategyVaildDate);
            });
        }
    }

    /**
     * 保存成本策略基本信息
     * @param localFunProduct               产品基本信息
     * @param LocalFunResourceStrategyReq   成本策略信息
     * @return
     */
    private LocalFunProductCostStrategy insertLocalFunProductCostStrategy(LocalFunProduct localFunProduct, LocalFunResourceStrategyReq LocalFunResourceStrategyReq) {
        LocalFunProductCostStrategy LocalFunProductCostStrategy = EntityUtil.convertBean(LocalFunResourceStrategyReq, LocalFunProductCostStrategy.class);
        LocalFunProductCostStrategy.setId(SnowflakeIdWorker.nextId());
        LocalFunProductCostStrategy.setProductId(localFunProduct.getId());
        localFunProductCostStrategyMapper.insert(LocalFunProductCostStrategy);
        return LocalFunProductCostStrategy;
    }


    /**
     * 保存产品基本信息
     * @param resourceProductReq    产品请求入参
     * @param tokenUser             当前用户
     * @return                      产品实体
     */
    private LocalFunProduct saveProductBaseInfo(LocalFunResourceProductReq resourceProductReq, TokenUser tokenUser) {
        LocalFunProduct localFunProduct = EntityUtil.copy(resourceProductReq, LocalFunProduct.class);
        if(localFunProduct.getId() != null && localFunProduct.getId() != 0L){
            localFunProduct.setGmtModified(LocalDateTime.now());
            localFunProduct.setModifiedId(tokenUser.getId());
            localFunProduct.setVaildDayBegin(resourceProductReq.getVaildDayBegin() != null ? resourceProductReq.getVaildDayBegin().atStartOfDay() : null);
            localFunProduct.setVaildDayEnd(resourceProductReq.getVaildDayEnd() != null ? resourceProductReq.getVaildDayEnd().atStartOfDay() : null);
            localFunProduct.setVaildType(resourceProductReq.getVaildType());
            localFunProduct.setVaildDay(resourceProductReq.getVaildDay());
            baseMapper.updateById(localFunProduct);
        }else {
            UserDTO userDTO = iSysUserService.loadUserByParam(tokenUser.getId(),1);
            localFunProduct.setId(SnowflakeIdWorker.nextId());
            //產品來源 1 API，2手動錄入
            localFunProduct.setSourceType(2);
            //上架狀態 0 未上架，1 已上架
            localFunProduct.setStatus(0);
            //推薦狀態 0 無，1已推薦
            localFunProduct.setIsRecommend(0);
            localFunProduct.setApprovalStatus(ApprovalStatus.WAIT_SUBMIT.getCode());
            localFunProduct.setProductCode(getProductNumber(userDTO));
            localFunProduct.setCreateId(tokenUser.getId());
            localFunProduct.setGmtCreate(LocalDateTime.now());
            localFunProduct.setGmtModified(LocalDateTime.now());
            baseMapper.insert(localFunProduct);
        }
        return localFunProduct;
    }

    public static String getProductNumber(UserDTO userDTO) {
        StringBuffer collectionNumber = new StringBuffer();
        collectionNumber.append("PW");
        collectionNumber.append(userDTO.getEmployeeNumber());
        String month = LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd"));
        collectionNumber.append(month);
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm"));
        collectionNumber.append(time);
        Random random = new Random();
        collectionNumber.append(random.nextInt(9)+"");
        collectionNumber.append(random.nextInt(9)+"");
        collectionNumber.append(random.nextInt(9)+"");
        collectionNumber.append(random.nextInt(9)+"");
        return collectionNumber.toString();
    }

    /**
     * 校验成本编码是否已存在
     * @param LocalFunResourceStrategyReqs
     * @return
     */
    private boolean existedStockNumberError(List<LocalFunResourceStrategyReq> LocalFunResourceStrategyReqs) {
        for (LocalFunResourceStrategyReq LocalFunResourceStrategyReq : LocalFunResourceStrategyReqs) {
            List<LocalFunResourceStockReq> LocalFunResourceStock = LocalFunResourceStrategyReq.getLocalFunResourceStock();
            if (CollectionUtils.isNotEmpty(LocalFunResourceStock)) {
                QueryWrapper<LocalFunProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().in(LocalFunProductCostStrategySpecStock::getStockNumber, LocalFunResourceStock.stream().map(LocalFunResourceStockReq::getStockNumber).collect(Collectors.toList()));
                if (localFunProductCostStrategySpecStockMapper.selectCount(queryWrapper) > 0) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public Result<Long> saveAgent(LocalFunProductSaveReq LocalFunProductSaveReq) {
        LocalFunProduct LocalFunProduct = localFunProductMapper.selectById(LocalFunProductSaveReq.getId());
        if(LocalFunProductSaveReq.getStartSaleTimeType() != null){
            LocalFunProduct.setStartSaleTimeType(LocalFunProductSaveReq.getStartSaleTimeType());
        }
        if(LocalFunProductSaveReq.getStartSaleTimeBegin() != null){
            LocalFunProduct.setStartSaleTimeBegin(LocalFunProductSaveReq.getStartSaleTimeBegin());
        }
        if(LocalFunProductSaveReq.getStartSaleTimeEnd() != null){
            LocalFunProduct.setStartSaleTimeEnd(LocalFunProductSaveReq.getStartSaleTimeEnd());
        }
        if(StringUtils.isNotEmpty(LocalFunProductSaveReq.getCustomerNotice())){
            LocalFunProduct.setCustomerNotice(LocalFunProductSaveReq.getCustomerNotice());
        }
        if(LocalFunProductSaveReq.getReserveChargeType() != null){
            LocalFunProduct.setReserveChargeType(LocalFunProductSaveReq.getReserveChargeType());
        }
        if(LocalFunProductSaveReq.getReserveCharge() != null){
            LocalFunProduct.setReserveCharge(LocalFunProductSaveReq.getReserveCharge());
        }
        if(LocalFunProductSaveReq.getCtsChargeType() != null){
            LocalFunProduct.setCtsChargeType(LocalFunProductSaveReq.getCtsChargeType());
        }
        if(LocalFunProductSaveReq.getCtsCharge() != null){
            LocalFunProduct.setCtsCharge(LocalFunProductSaveReq.getCtsCharge());
        }
        if(LocalFunProductSaveReq.getNeedInfo() != null){
            LocalFunProduct.setNeedInfo(LocalFunProductSaveReq.getNeedInfo());
        }
        if(LocalFunProductSaveReq.getBookConfirm() != null){
            LocalFunProduct.setBookConfirm(LocalFunProductSaveReq.getBookConfirm());
        }
        if(LocalFunProductSaveReq.getCancelPolicy() != null){
            LocalFunProduct.setCancelPolicy(LocalFunProductSaveReq.getCancelPolicy());
        }
        if(StringUtils.isNotEmpty(LocalFunProductSaveReq.getCertificateTypeIds())){
            LocalFunProduct.setCertificateType(LocalFunProductSaveReq.getCertificateTypeIds());
        }
        baseMapper.updateById(LocalFunProduct);

        //已上架的产品才做缓存更新
        if(LocalFunProduct.getStatus() == 1){
            //刷新缓存
            try {
                CompletableFuture.runAsync(() -> {
                    LocalFunProductCacheOpsReq req = new LocalFunProductCacheOpsReq();
                    req.setIds(Lists.newArrayList(LocalFunProduct.getId()));
                    iLocalFunAppProductService.cacheUpdate(req);
                });
                log.info("[当地玩乐-预定设置] 同步缓存成功");
            } catch (Exception e) {
                log.info("[当地玩乐-预定设置] 同步缓存失败：{}",e.getMessage());
            }
        }
        return Result.success(LocalFunProduct.getId());
    }

    @Override
    public Result<LocalFunResourceDetailDTO> detail(Long id, LocalDate queryDate, TokenUser currentUser) {
        //1.产品信息
        LocalFunProduct localFunProduct = baseMapper.selectById(id);

        //2.获取产品成本策略结果集
        LocalFunResourceDetailDTO localFunResourceDetailDTO = EntityUtil.convertBean(localFunProduct, LocalFunResourceDetailDTO.class);
        if(StringUtils.isNotEmpty(localFunProduct.getCertificateType())){
            String[] split = localFunProduct.getCertificateType().split(",");
            localFunResourceDetailDTO.setCertificateTypeList(Arrays.asList(split));
        }
        QueryWrapper<LocalFunProductCostStrategy> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunProductCostStrategy::getProductId, localFunProduct.getId());
        List<LocalFunProductCostStrategy> LocalFunProductCostStrategies = localFunProductCostStrategyMapper.selectList(queryWrapper);

        //3.遍历产品成本，查询填充有效期、规格、成本价
        List<LocalFunResourceStrategyReq> LocalFunResourceStrategyReqs = EntityUtil.copyList(LocalFunProductCostStrategies, LocalFunResourceStrategyReq.class);
        LocalFunResourceStrategyReqs.forEach(LocalFunProductCostStrategy -> {
            QueryWrapper<LocalFunProductCostStrategyVaildDate> dateQueryWrapper = new QueryWrapper<>();
            dateQueryWrapper.lambda().eq(LocalFunProductCostStrategyVaildDate::getProductId, localFunProduct.getId());
            dateQueryWrapper.lambda().eq(LocalFunProductCostStrategyVaildDate::getCostId, LocalFunProductCostStrategy.getId());
            List<LocalFunProductCostStrategyVaildDate> LocalFunProductCostStrategyVaildDates = localFunProductCostStrategyVaildDateMapper.selectList(dateQueryWrapper);
            //设置有效期
            LocalFunProductCostStrategy.setTimeList(LocalFunProductCostStrategyVaildDates.stream().map(entity->{
                LocalFunResourceStrategyTimeReq resourceStrategyTimeReq = new LocalFunResourceStrategyTimeReq();
                resourceStrategyTimeReq.setTimeBegin(DateUtil.fmtLocalDate(entity.getTimeBegin(),"yyyy-MM-dd"));
                resourceStrategyTimeReq.setTimeEnd(DateUtil.fmtLocalDate(entity.getTimeEnd(),"yyyy-MM-dd"));
                return resourceStrategyTimeReq;
            }).collect(Collectors.toList()));

            //设置规格
            QueryWrapper<LocalFunProductCostStrategySpecAttr> attrQueryWrapper = new QueryWrapper<>();
            attrQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecAttr::getProductId, localFunProduct.getId());
            attrQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecAttr::getCostId, LocalFunProductCostStrategy.getId());
            List<LocalFunProductCostStrategySpecAttr> specAttrList = strategySpecAttrMapper.selectList(attrQueryWrapper);
            LocalFunProductCostStrategy.setSpecList(EntityUtil.copyList(specAttrList, LocalFunResourceSpecReq.class));

            //设置规格成本价
            QueryWrapper<LocalFunProductCostStrategySpecStock> specStockQueryWrapper = new QueryWrapper<>();
            specStockQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getProductId, localFunProduct.getId());
            specStockQueryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getCostId, LocalFunProductCostStrategy.getId());
            List<LocalFunProductCostStrategySpecStock> LocalFunProductCostStrategySpecStocks = localFunProductCostStrategySpecStockMapper.selectList(specStockQueryWrapper);
            LocalFunProductCostStrategy.setLocalFunResourceStock(EntityUtil.copyList(LocalFunProductCostStrategySpecStocks, LocalFunResourceStockReq.class));

//            setCostPrice(queryDate, currentUser, localFunProduct, LocalFunProductCostStrategy);

        });
        localFunResourceDetailDTO.setLocalFunResourceStrategy(LocalFunResourceStrategyReqs);
        setDicData(localFunResourceDetailDTO);
        localFunResourceDetailDTO.setProductId(localFunProduct.getId());
        ProcessorUtil.process(localFunResourceDetailDTO,LocalFunResourceDetailDTO.class);
        if(localFunResourceDetailDTO.getReserveCharge() == null){
            localFunResourceDetailDTO.setReserveCharge(BigDecimal.ZERO);
            //1 數值 2 百分比
            localFunResourceDetailDTO.setReserveChargeType(1);
        }
        if(localFunResourceDetailDTO.getCtsCharge() == null){
            localFunResourceDetailDTO.setCtsCharge(BigDecimal.ZERO);
            //1 數值 2 百分比
            localFunResourceDetailDTO.setCtsChargeType(1);
        }
        return Result.success(localFunResourceDetailDTO);
    }

    private void setDicData(LocalFunResourceDetailDTO localFunResourceDetailDTO) {
        //使用有效期
        localFunResourceDetailDTO.setValidateScope(getValidateScope(localFunResourceDetailDTO));
        //開售時間
        localFunResourceDetailDTO.setStartSaleScope(getStartSaleScope(localFunResourceDetailDTO));
    }

    /**
     * 获取开售时间范围
     * @param localFunResourceDetailDTO
     * @return
     */
    private String getStartSaleScope(LocalFunResourceDetailDTO localFunResourceDetailDTO) {
        LocalDateTime startSaleTimeBegin = localFunResourceDetailDTO.getStartSaleTimeBegin();
        LocalDateTime startSaleTimeEnd = localFunResourceDetailDTO.getStartSaleTimeEnd();
        if(startSaleTimeBegin == null || startSaleTimeEnd == null){
            return "";
        }
        String startTime = DateUtil.fmt(startSaleTimeBegin, "yyyy.MM.dd");
        String endTime = DateUtil.fmt(startSaleTimeEnd, "yyyy.MM.dd");
        return startTime + "-" + endTime;
    }

    /**
     * 获取使用期范围
     * @param localFunResourceDetailDTO
     * @return
     */
    private String getValidateScope(LocalFunResourceDetailDTO localFunResourceDetailDTO) {
        if(localFunResourceDetailDTO.getVaildType() != null && ProductCenterEnum.VAILDTYPE_FIX.getChannelCode().equals(localFunResourceDetailDTO.getVaildType())){
            return "訂購後" + localFunResourceDetailDTO.getVaildDay() +"天內有效";
        }
        LocalDateTime startSaleTimeBegin = localFunResourceDetailDTO.getVaildDayBegin();
        LocalDateTime startSaleTimeEnd = localFunResourceDetailDTO.getVaildDayEnd();
        if(startSaleTimeBegin == null || startSaleTimeEnd == null){
            return "";
        }
        String startTime = DateUtil.fmt(startSaleTimeBegin, "yyyy.MM.dd");
        String endTime = DateUtil.fmt(startSaleTimeEnd, "yyyy.MM.dd");
        return startTime + "-" + endTime;
    }

    /**
     * 展示价格=成本价+幅加费
     * @param queryDate
     * @param currentUser
     * @param localFunProduct
     * @param LocalFunProductCostStrategy
     */
    private void setCostPrice(LocalDate queryDate, TokenUser currentUser, LocalFunProduct localFunProduct, LocalFunResourceStrategyReq LocalFunProductCostStrategy) {
        LocalFunProductCostReq localFunProductCostReq = new LocalFunProductCostReq();
        localFunProductCostReq.setUserId(currentUser.getId());
        localFunProductCostReq.setProductId(localFunProduct.getId());
        localFunProductCostReq.setQueryDate(queryDate);
        localFunProductCostReq.setChannelType(1);
        LocalFunOfflineSelCustomDTO increaseFee = iLocalFunCostPriceService.getIncreaseFee(localFunProductCostReq);

        BigDecimal exchangeRate = LocalFunProductCostStrategy == null ? BigDecimal.ZERO : mainDataCurrencyService.getExchangeRate(LocalFunProductCostStrategy.getCurrency(),
                CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);

        LocalFunProductCostStrategy.getLocalFunResourceStock().forEach(entity->{
            BigDecimal costPrice = entity.getCostPrice();
            costPrice = costPrice == null ? BigDecimal.ZERO : costPrice.multiply(exchangeRate);
            entity.setCostPrice(increaseFee == null ? costPrice : ( ProductCenterEnum.AMOUNT.getChannelCode().equals(increaseFee.getAdjustType())?
                    //成本价+幅加费 金额
                    costPrice.add(increaseFee.getAmount()):
                    //成本价+(幅加费=成本价*百分比) 百分比
                    costPrice.add(costPrice.multiply(BigDecimal.valueOf(increaseFee.getPercent())))));
        });
    }

    @Override
    public Result<Long> updateApi(LocalFunResourceApiReq resourceApiReq) {
        super.updateBatchById(baseMapper.selectBatchIds(resourceApiReq.getIds())
                .stream()
                .filter(item -> item.getSourceType().equals(2))
                .peek(scenicProduct -> {
                    if(resourceApiReq.getAllowPackage() != null){
                        scenicProduct.setAllowPackage(resourceApiReq.getAllowPackage());
                    }
                    if(resourceApiReq.getSaleStatus() != null){
                        scenicProduct.setSaleStatus(resourceApiReq.getSaleStatus());
                    }
                    scenicProduct.setChargeUserId(resourceApiReq.getChargeUserId());
                    scenicProduct.setChargeUser(resourceApiReq.getChargeUser());
                }).collect(Collectors.toList()));
        return Result.success(resourceApiReq.getIds().get(0));
    }

    @Override
    public Result<String> submit(LocalFunProductSubmitReq localFunProductSubmitReq, TokenUser tokenUser) {

        Result<ApprovalStartDTO> result = iSysApprovalService.start(SystemBusinessType.LOCAL_FUN.getCode(),
                SysApprovalType.ADD_LOCALFUN.getCode(),Long.parseLong(localFunProductSubmitReq.getId()),tokenUser.getId(),null,null);
        if(result.isSuccess()){
            LocalFunProduct scenicProduct = baseMapper.selectById(localFunProductSubmitReq.getId());
            scenicProduct.setApprovalStatus(ApprovalStatus.REVIEWING.getCode());
            scenicProduct.setModifiedId(tokenUser.getId());
            scenicProduct.setGmtModified(LocalDateTime.now());
            baseMapper.updateById(scenicProduct);
        }else {
            Result result1 = new Result();
            result1.setCode(result.getCode());
            result1.setMsg(result.getMsg());
            return result1;
        }
        return Result.success(localFunProductSubmitReq.getId());
    }

    @Override
    public Result<LocalFunResourceDetailDTO> productDetail(Long id) {
        LocalFunProduct localFunProduct = localFunProductMapper.selectById(id);
        return Result.success(EntityUtil.copy(localFunProduct,LocalFunResourceDetailDTO.class));
    }

    @Override
    public Result<Long> updateApproveStatus(LocalFunUpdateApproveStatusReq req) {
        UpdateWrapper<LocalFunProduct> updateWrapper = new UpdateWrapper<>();
        if(req.getApproveStatus() != null){
            updateWrapper.set("approval_status",req.getApproveStatus());
        }
        if(req.getSaleStatus() != null){
            updateWrapper.set("sale_status",req.getSaleStatus());
        }
        updateWrapper.lambda().eq(LocalFunProduct::getId,req.getProductId());
        localFunProductMapper.update(null, updateWrapper);
        return Result.success(req.getProductId());
    }

    @Override
    public PageResponse<LocalFunResourceDTO> queryListByProductIds(LocalFunResourceReq localFunResourceReq) {
        IPage<LocalFunProduct> iPage = new Page<>(localFunResourceReq.getPageNo(), localFunResourceReq.getPageSize());
        //查询条件
        QueryWrapper<LocalFunProduct> queryWrapper = queryParamCondition(localFunResourceReq, null);
        //查询审批通过的产品
        queryWrapper.lambda().eq(LocalFunProduct::getApprovalStatus,3);
        queryWrapper.orderByDesc("gmt_create");
        //分页查询结果集
        IPage<LocalFunProduct> insuranceIPage = baseMapper.selectPage(iPage, queryWrapper);

        if (CollectionUtils.isNotEmpty(insuranceIPage.getRecords())) {
            List<LocalFunResourceDTO> localFunResourceDTOList = EntityUtil.copyList(insuranceIPage.getRecords(), LocalFunResourceDTO.class);
            ProcessorUtil.processMore(localFunResourceDTOList,LocalFunResourceDTO.class);
            return new PageResponse<>(localFunResourceDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
//    @GlobalTransactional(rollbackFor = Exception.class)
    public void testTX() {
//        LocalFunProduct localFunProduct = new LocalFunProduct();
//        localFunProduct.setId(SnowflakeIdWorker.nextId());
//        localFunProductMapper.insert(localFunProduct);
//        AddSysUserReq addSysUserReq = new AddSysUserReq();
//        addSysUserReq.setUsername("JACL");
//        iSysUserService.addUser(addSysUserReq,1L);
    }

    @Override
    public Result<Long> check(LocalFunProductCheckReq localFunProductCheckReq, TokenUser currentUser) {
        Result<ApprovalCheckDTO> result = iSysApprovalService.check(localFunProductCheckReq.getId(),currentUser.getId(),localFunProductCheckReq.getStatus(),localFunProductCheckReq.getReason());
        if(result.isSuccess()){
            if(result.getData().getIsFinish()){
                LocalFunProduct localFunProduct = baseMapper.selectById(localFunProductCheckReq.getProductId());
                localFunProduct.setModifiedId(currentUser.getId());
                localFunProduct.setGmtModified(LocalDateTime.now());
                //撤回和审批不通过
                if(localFunProductCheckReq.getStatus() == 0 || localFunProductCheckReq.getStatus() == 4){
                    localFunProduct.setApprovalStatus(1);
                }
                if(localFunProductCheckReq.getStatus() == 3){
                    //审批通过
                    localFunProduct.setSaleStatus(1);
                    localFunProduct.setApprovalStatus(3);
                }
                baseMapper.updateById(localFunProduct);
            }
        }else {
            Result result1 = new Result();
            result1.setCode(result.getCode());
            result1.setMsg(result.getMsg());
            return result1;
        }
        return Result.success(localFunProductCheckReq.getId());
    }


    /**
     * 产品列表查询条件
     * @param req 查询条件请求参数值
     * @param id
     * @return    queryWrapper
     */
    private QueryWrapper<LocalFunProduct> queryParamCondition(LocalFunResourceReq req, Long id) {
        QueryWrapper<LocalFunProduct> queryWrapper = new QueryWrapper<>();
        //城市名称 模糊
        if (req.getCityId() != null) {
            queryWrapper.lambda().eq(LocalFunProduct::getCityId, req.getCityId());
        }
        //城市名称 模糊
        if (StringUtils.isNotBlank(req.getProductCode())) {
            queryWrapper.lambda().eq(LocalFunProduct::getProductCode, req.getProductCode());
        }
        //城市名称 模糊
        if (StringUtils.isNotBlank(req.getCityName())) {
            queryWrapper.lambda().like(LocalFunProduct::getCityName, req.getCityName());
        }
        //供应商名称 模糊
        if (req.getSupplierId() != null) {
            queryWrapper.lambda().like(LocalFunProduct::getSupplierId, req.getSupplierId());
        }
        //供应商名称 模糊
        if (StringUtils.isNotBlank(req.getSupplierName())) {
            queryWrapper.lambda().like(LocalFunProduct::getSupplierName, req.getSupplierName());
        }
        //产品类型
        if (null != req.getFunType() && req.getFunType() != 0L) {
            queryWrapper.lambda().eq(LocalFunProduct::getFunType, req.getFunType());
        }
        //销售状态
        if (null != req.getSaleStatus()) {
            queryWrapper.lambda().eq(LocalFunProduct::getSaleStatus, req.getSaleStatus());
        }
        //审批状态
        if (null != req.getStatus()) {
            queryWrapper.lambda().eq(LocalFunProduct::getStatus, req.getStatus());
        }
        //审批状态
        if (null != req.getApprovalStatus()) {
            queryWrapper.lambda().eq(LocalFunProduct::getApprovalStatus, req.getApprovalStatus());
        }
        //是否允许自由打包
        if (null != req.getAllowPackage()) {
            queryWrapper.lambda().eq(LocalFunProduct::getAllowPackage, req.getAllowPackage());
        }
        //产品名称
        if (StringUtils.isNotEmpty(req.getName())) {
            queryWrapper.lambda().like(LocalFunProduct::getName, req.getName());
        }
        if(CollectionUtils.isNotEmpty(req.getProductIds())){
            queryWrapper.lambda().in(LocalFunProduct::getId,req.getProductIds());
        }
        //用户ID
        if(id != null){
            queryWrapper.lambda().eq(LocalFunProduct::getCreateId,id)
                    .or().eq(LocalFunProduct::getChargeUserId,id);
        }
        return queryWrapper;
    }
}
